<%@ path=/compile/${filename}%>
<%
	int line = -1;

	param_string(flag);
	param_string(path);
	param_string(icon);
	param_string(title);
	param_string(source);
	param_string(keyword);
	
	if (title.empty()) title = "C++编译器";

	if (icon.empty()) icon = "/res/img/note/code.png";

	if (source.empty() && path.length() > 0 && path.length() < 1024)
	{
		HttpRequest request;

		request.init(path);
		request.setHeadValue("Cookie", this->request->getHeadValue("Cookie"));

		sp<HttpResponse> response = app->getLocaleResult(request);

		if (response)
		{
			SmartBuffer buffer = response->getResult();
			
			if (buffer.size() > 0 && buffer.size() < 256 * 1024) source = buffer.str();
		}
	}

	if (source.length() > 256 * 1024) source.clear();
	
	if (source.length() > 0)
	{
		if (keyword.length() > 0)
		{
			size_t pos = source.find(keyword);
			
			if (pos != string::npos)
			{
				line = 0;

				for (size_t i = 0; i < pos; i++)
				{
					if (source[i] == '\n') ++line;
				}
			}
		}

		source = stdx::replace(source, "\\", "\\\\");
		source = stdx::replace(source, "\n", "\\n");
		source = stdx::replace(source, "\r", "\\r");
		source = stdx::replace(source, "\t", "\\t");
		source = stdx::replace(source, "\"", "\\\"");
		source = stdx::replace(source, "\'", "\\\'");
	}
%>
<!DOCTYPE HTML>
<html>
<head>
<title><%=title%></title>
<meta name='referrer' content='always'/>
<link rel='shortcut icon' href='<%=icon%>'/>
<meta name='keywords' content='C++在线编译器'/>
<meta name='description' content='C++在线编译器'/>
<meta http-equiv='x-ua-compatible' content='ie=edge,chrome=1'/>
<meta http-equiv='content-type' content='text/html; charset=utf-8'/>
<meta name='viewport' content='width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no'/>

<link rel='stylesheet' type='text/css' href='/app/workspace/css/base.css'/>
<link rel='stylesheet' type='text/css' href='/res/lib/codemirror/lib/codemirror.css'/>
<link rel='stylesheet' type='text/css' href='/res/lib/codemirror/addon/fold/foldgutter.css'/>

<script>
if (typeof(require) == 'function') delete window.module;
</script>

<script src='/res/lib/utils.js.gzip'></script>
<script src='/res/lib/codemirror/lib/codemirror.js.gzip'></script>

<script src='/res/lib/codemirror/mode/clike/clike.js'></script>
<script src='/res/lib/codemirror/addon/fold/foldcode.js'></script>
<script src='/res/lib/codemirror/addon/fold/foldgutter.js'></script>
<script src='/res/lib/codemirror/addon/fold/brace-fold.js'></script>
<script src='/res/lib/codemirror/addon/fold/indent-fold.js'></script>
<script src='/res/lib/codemirror/addon/fold/comment-fold.js'></script>
  
<style>
#SideDiv{
	background: #FFF;
}
#MainDiv{
	display: none;
}
#CodeDiv{
	margin-top: 2px;
	border: 1px solid #CCC;
}
#OutputDiv{
<%if (flag == "V"){%>
	display: none;
<%}%>
	padding-top: 3px;
	border: 1px solid #CCC;
}
#OutputText{
	overflow: scroll;
	margin-top: 3px;
	border-top: 1px solid #CCC;
	background: rgba(255, 255, 255, 0.6);
}
#SideDiv div{
	font-weight: bold;
}
#CmdParamDiv{
<%if (flag == "V"){%>
	display: none;
<%}%>
}
#CompileButton{
	color: #090;
}
#SaveCodeButton{
	color: #090;
}
#OutputViewDiv{
	width: 40vw;
	height: 50vh;
	padding: 8px;
	overflow: auto;
	background: #EEE;
	margin: 4px 8px 11px;
	border: 1px solid #27F;
}
.OutputPage{
	padding: 0px 4px;
	white-space: pre-wrap;
	word-wrap: break-word;
}
.MenuTableTd{
	padding-right: 4px;
}
.CodeOperLink{
	float: right;
	margin-left: 4px;
	margin-right: 4px;
	text-decoration: none;
}
.FileUploadButton{
	height: 18px;
	padding: 0px 1px;
	line-height: 18px;
}
.CodeMirror{
	background: rgba(255, 255, 255, 0.6);
}
.CodeMirror-gutters{
	background: rgba(255, 255, 255, 0.7);
}
</style>

<script>
var idx = 0;
var code = null;
var param = null;
var dbconn = null;
var menubar = null;
var menubox = null;
var viewcode = true;
var curtitle = null;
var curcontent = null;
var outputmenubox = null;

var line = <%=line%>;
var source = '<%=source%>';

if (typeof(require) == 'function' && strlen(source) <= 0){
	loadScript('/sys/node.js').onload = function(){
		var path = shell.argv[1];
		if (path){
			var pos = shell.size(path);
			if (pos > 8 && pos < 256 * 1024){
				source = shell.read(path);
			}
		}
	}
}

function addCode(saved){
	var content = code.getValue();

	if (saved == null && strlen(content) > 0 && strlen(curtitle) > 0) saveCode(curtitle, content, false);

	var msgbox = showConfirmMessage("<table class='DialogTable'><tr><td><v-text id='AddCodeTitleText' title='代码名称' size='14' maxlength='20'></v-text></td></tr></table>", '新建代码', function(flag){
		if (flag == 0) return true;

		var title = $('#AddCodeTitleText').val();

		if ((len = strlen(title)) == 0){
			$('#AddCodeTitleText').focus();
			return false;
		}

		if (len > 24){
			showToast('代码名称最多12个汉字或24个英文字母');
			$('#AddCodeTitleText').focus();
			return false;
		}

		dbconn.query('select * from cppcode where title=?', [title], function(result){
			if (result.length > 0){
				showToast('已有名称相同的代码');
				$('#AddCodeTitleText').focus();
			}
			else{
				hideMsgBox();

				removeStorage("compile_cppcode");

				if (curtitle == null && strlen(content) > 0) saved = true;

				saveCode(title, saved ? content : source);
			}
		});
	
		return false;
	});
	
	$('#AddCodeTitleText').keydown(function(e){
		if (e.which == 13) msgbox.confirm();
	});
}

function exportCode(){
	dbconn.query('select * from cppcode', function(result){
		if (result.length <= 0){
			showToast('你还没有创建任何代码');
		}
		else{
			saveAs(JSON.stringify(result), getShortDateTimeString() + '.code');
		}
	});
}

function importCode(content){
	try{
		var num = 0;
		var result = JSON.parse(content);
		
		if (result == null || result.length == null || result.length <= 0){
			showToast('导入文件格式错误');
			return false;
		}

		for (var i = 0; i < result.length; i++){
			var item = result[i];

			if (strlen(item.title) > 0 && strlen(item.content) > 0){
				dbconn.execute('insert into cppcode(title,content,statetime) values(?,?,?)', [unescape(item.title), unescape(item.content), item.statetime]);
			}
		}

		setTimeout(updateView, 100);
		showToast('本地代码导入成功');
		return true;
	}
	catch(e){
		showToast('导入文件格式错误');
		return false;
	}
}

function removeCode(title){
	showConfirmMessage('确定要将代码[' + title + ']删除?', '删除代码', function(flag){
		dbconn.execute('delete from cppcode where title=?', [title],
			function(stmt, result){
				if (title == curtitle) curtitle = null;
				updateView();
			}
		);
	});
}

function selectCode(title){
	dbconn.query('select * from cppcode where title=?', [title], function(result){
			if (result.length > 0){
				code.setValue(result[0].content);
				curcontent = code.getValue();
				curtitle = title;
			}
		}
	);
}

function saveCode(title, content, showtoast){
	if (showtoast == null) showtoast = true;

	if (title && title == curtitle){
		dbconn.execute('update cppcode set content=? where title=?', [content, title],
			function(stmt, result){
				if (showtoast) showToast('代码保存成功');
				curcontent = content;
				updateView();
			}
		);
	}
	else{
		if (title == null){
			addCode(true);
		}
		else{
			dbconn.execute('insert into cppcode(title,content,statetime) values(?,?,?)', [title, content, getDateTimeString()], function(stmt, result){
				updateView();
			});
		}
	}
}

function hideSideWindow(){
	$('#TopDiv').remove();
	$('#SideDiv').remove();
	$('#BottomDiv').remove();
	$('#ImportCodeButton').remove();
	$('#ExportCodeButton').remove();
}

function updateView(){
	if (dbconn == null) return code.setValue(source);

	dbconn.query('select * from cppcode order by statetime desc', function(result){
		var time = null;
		var label = null;
		
		menubar.clear();

		if (result.length <= 0){
			code.setValue(source);
			curtitle = null;
		}
		else{
			result.forEach(function(item){
				var node = menubar.add(item.title, '/res/img/file/cpp.png', function(){
					var content = code.getValue();

					if (strlen(content) == 0 || strlen(curcontent) == 0 || content == curcontent){
						selectCode(item.title);
					}
					else{
						showConfirmMessage('是否要保存当前代码？', '保存代码', function(flag){
							if (flag) saveCode(curtitle, content);
							selectCode(item.title);
						});
					}
				});

				menubox.bind(node);

				if (strlen(curtitle) == 0){
					if (time == null || time < item.statetime){
						time = item.statetime;
						label = node;
					}
				}
				else{
					if (curtitle == item.title) label = node;
				}

			});
		}

		if (label) label.click();
	});
}

function sponsor(){
	var box = showToastMessage("<div style='width:256px;height:300px'></div>", true, null, null, function(){
		$(box.dialog).css('background-image', '');
	});
	$(box.dialog).css('background-size', '100% 100%').css('background-image', 'url(/res/img/receipt.png)');
	centerWindow(box.dialog);
}

function compile(){
	var cmd = param.val();
	var output = $('#OutputText');
	var content = code.getValue();

	if (strlen(cmd) > 0xFF){
		showToast('命令行参数太长');
		return param.focus();
	}

	if (!isFilePath(cmd, false)){
		showToast('命令行参数不能有特殊字符');
		return param.focus();
	}

	if (strlen(content) == 0) return code.focus();

	output.html('');
	result = null;

	showToastMessage('正在编译代码...');

	if (!viewcode && dbconn == null) setStorage('compile_cppcode', content);

	getHttpResult('/compile/compile', {code: content, param: cmd}, function(data){
		result = data;
		hideToastBox();

		if (data.code == XG_PARAMERR){
			if (data.output){
				output.html("<font color='#EE0000'><pre class='OutputPage'>" + data.output + "</pre></font>");
			}
			else{
				output.html("<font color='#EE0000'><pre class='OutputPage'>源码编译失败</pre></font>");
			}
		}
		else if (data.code == XG_TIMEOUT){
			output.html("<font color='#EE0000'><pre class='OutputPage'>执行超时(源码中可能存在耗时操作)</pre></font>");
		}
		else if (data.code == XG_SYSBUSY){
			if (idx++ < 50){
				compile();
			}
			else{
				showToast('系统繁忙---请稍后再试');

				idx = 0;
			}
		}
		else if (data.code < 0){
			if (data.status && data.status == 403){
				showToast('访问频繁请稍后再试');
			}
			else{
				showToast('源码编译失败');
			}
		}
		else{
			outputmenubox.bind(output);

			output.html("<pre class='OutputPage'>" + data.output + "</pre>");

			if (data.result && isJsonString(data.result)) data['json'] = data.result;
		}
	}, true);
}

function saveAs(text, filename){
	if (!!window.ActiveXObject || 'ActiveXObject' in window){
		showToast('当前浏览器不支持本地导出---您可以使用其他浏览器进行导出');
	}
	else{
		var a = document.createElement('a');

		a.setAttribute('href', 'data:text/plain,' + escape(text));
		a.setAttribute('download', filename);
		a.setAttribute('target', '_blank');
		a.style.display = 'none';

		appendCtrl(a);
		a.click();

		$(a).remove();
	}
}

function getFileContent(file, callback){
	if (window.FileReader){
		var reader = new FileReader();
		reader.onloadend = function(e){
			if (e.target.readyState == FileReader.DONE) callback(e.target.result);
		}
		reader.readAsText(file);
	}
};

window.onload = function(){
	loadStyle('/res/lib/jsonformat/format.css');
	loadScript('/res/lib/jsonformat/format.js');

	menubox = new ContextMenu(['打开', '删除'], function(text, elem){
		if (text == '删除'){
			removeCode(elem.text);
		}
		else{
			elem.click();
		}
	});

	outputmenubox = new ContextMenu(['复制', '预览'], function(text, attach, menuitem){
		if (text == '复制'){
			setClipboard(result.result, '输出内容已复制到剪切板');
		}
		else{
			if (result.json){
				var toastbox = showToastMessage("<div id='OutputViewDiv' class='HiddenScrollbar'></div>", true, null, null, true);
				var format = new JsonFormatter({dom: getCtrl('OutputViewDiv')});
				toastbox.dialog.style.userSelect = 'auto';
				format.doFormat(result.json);
			}
			else{
				showToastMessage("<textarea id='OutputViewDiv'></textarea>", true, null, null, true);
				$('#OutputViewDiv').val(result.result);
			}
		}
	});

	var text = "<div><span>我的代码</span><span style='float:right'><a class='CodeOperLink' style='color:#090;' onclick='addCode()' href='javascript:void(0)'>添加</a><a class='CodeOperLink' onclick='exportCode()' href='javascript:void(0)'>导出</a><a class='CodeOperLink' onclick=\"$('#ImportCodeButton .FileUploadButton').click()\" href='javascript:void(0)'>导入</a></span>";
	menubar = new MenuBar('SideDiv', text, '/res/img/menu/folder.png', null, null, false);
	menubar.color({
		color: '#4AA',
		hovercolor: '#000',
		selectcolor: '#4AA',
		barcolor: 'rgba(0, 0, 0, 0)',
		listcolor: 'rgba(0, 0, 0, 0)'
	});

	getVue('ContentDiv');

	try{
		dbconn = new DBConnect("compile_cppcode");
	}
	catch(e){
		dbconn = null;
	}

	if (strlen(source) == 0){
		viewcode = false;

		source = getStorage("compile_cppcode");

		if (strlen(source) == 0) source = getHttpResult('/app/compile/pub/compile.cpp');
	}
	else{
		$('#SaveCodeButton').remove();
	}

	var height = getClientHeight();

	window.onresize = function(){
		height = getClientHeight();
	<%if (flag == "V"){%>
		$('#CodeDiv').height(height - 4);
	<%}else{%>
		$('#CodeDiv').height(height - height / 5 - 66);
		$('#OutputText').height(height / 5);
	<%}%>
	}

	window.onresize();

	<%if (flag == "V"){%>
		hideSideWindow();
	<%}else{%>
		if (dbconn == null){
			hideSideWindow();
		}
		else{
			function updateContentView(){
				if (viewcode){
					hideSideWindow();
				}
				else{
					if (machinetype == 'PC'){
						setFrameStyle('TopDiv', 'SideDiv', 'MainDiv', 'BottomDiv', 0, 220, 0);
					}
					else{
						$('#ImportCodeButton').remove();
						$('#ExportCodeButton').remove();
					}
				}
			}

			dbconn.execute("create table cppcode(title text,content text,statetime text,primary key(title))", function(dbconn, result){
				saveCode('示例代码', source);
				updateContentView();
			},
			function(stmt, result){
				updateContentView();
			});
		}
	<%}%>

	code = CodeMirror.fromTextArea(document.getElementById('CodeText'), {
		mode: 'text/x-csrc',
		tabSize: 4,
		indentUnit: 4,
		inputStyle: 'textarea',
		foldGutter: true,
		lineNumbers: true,
		lineWrapping: true,
		matchBrackets: true,
		indentWithTabs: true,
		styleActiveLine: true,
		showCursorWhenSelecting: true,
		gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter']
	});

	code.setSize('100%','100%');
	setLabelText('CompileButton', '执行');
	setLabelText('SaveCodeButton', '保存');
	setLabelText('CopyCodeButton', '复制');
	param = QueryWidget('CmdParamDiv', '输入命令行程序启动参数', '执行', compile);

	$('#MainDiv').show();

	$('#SaveCodeButton').click(function(){
		var content = code.getValue();

		if (strlen(content) > 0){
			if (dbconn == null){
				setStorage('compile_cppcode', content);

				showToast('代码保存成功');
			}
			else{
				saveCode(curtitle, content);
			}
		}
	});

	$('#CompileButton').click(function(){
		compile();
	});

	if (true){
		openbutton = new UploadFileWidget('ImportCodeButton', '导入', null, 4 * 1024 * 1024);
		setLabelText('ExportCodeButton', '导出');
		openbutton.setFilter('.code');
		openbutton.label.hide();

		if (getBrowserInfo().prefix == 'ms'){
			$('#ExportCodeButton').parent().remove();
		}

		openbutton.change(function(file){
			getFileContent(file, function(text){
				importCode(text);
			});
			return false;
		});

		$('#ExportCodeButton').click(function(){
			exportCode();
		});
	}

	$('#CopyCodeButton').click(function(){
		setClipboard(code.getValue(), '源码已复制到剪切板');
	});

	code.setValue('\n\n\n\n\n\n\n\n\n\n');

	<%if (flag == "V"){%>
		code.setValue(source);
	<%}else{%>
		if (viewcode){
			code.setValue(source);
		}
		else{
			code.setValue('');

			setTimeout(updateView, 100);

			if (machinetype == 'PC'){
				$('body').append(getHttpResult('/promote/adlistbar', {left: 10, bottom: 6, width: 200, path: '编程'}));
			}
		}
	<%}%>

	if (line >= 0){
		setTimeout(function(){
			code.setSelection({line: line, ch: 0}, {line: line, ch: 1000}, {scroll: true});
		}, 500);
	}
}
</script>
</head>

<body>
	<div id='TopDiv'></div>
	<div id='SideDiv'></div>
	<div id='MainDiv'>
		<div id='ContentDiv'>
			<div id='CmdParamDiv'></div>
			<div id='CodeDiv'>
				<textarea id='CodeText'></textarea>
			</div>
			<div id='OutputDiv'>
				<table id='MenuTable'>
					<tr>
						<td class='MenuTableTd'>[程序输出]&nbsp;</td>
						<td class='MenuTableTd'><input class='FileUploadButton' id='CompileButton' onfocus='this.blur()' readonly/></td>
						<td class='MenuTableTd'><input class='FileUploadButton' id='SaveCodeButton' onfocus='this.blur()' readonly/></td>
						<td class='MenuTableTd'><input class='FileUploadButton' id='CopyCodeButton' onfocus='this.blur()' readonly/></td>
						<td class='MenuTableTd'><span id='ImportCodeButton'></span></td>
						<td class='MenuTableTd'><input class='FileUploadButton' id='ExportCodeButton' onfocus='this.blur()' readonly/></td>
						<td v-if="machinetype=='PC'" class='MenuTableTd'>&nbsp;&nbsp;<a class='TextLink' onclick='sponsor()' href='javascript:void(0)'>赞助我们</a></td>
						<td v-if="machinetype=='PC'" class='MenuTableTd'>&nbsp;<a class='TextLink' target='_blank' href='/'>赢锋主页</a></td>
						<td v-if="machinetype=='PC'" class='MenuTableTd'>&nbsp;<a class='TextLink' target='_blank' href='http://www.runoob.com/cplusplus/cpp-basic-syntax.html'>学习教程</a></td>
						<td v-if="machinetype=='PC'" class='MenuTableTd'>&nbsp;<a class='TextLink' target='_blank' href='https://zh.cppreference.com/w/cpp'>参考手册</a></td>
					</tr>
				</table>
				<div id='OutputText'></div>
			</div>
		</div>
	</div>
	<div id='BottomDiv'></div>
</body>
</html>